Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable serialization of the connection #264

Closed
wants to merge 2 commits into from
Closed

Conversation

richt222
Copy link

Adds the SerializesConnections trait to the Connection class, enabling its serialization.

It is sometimes necessary to serialize the connection, as it is dispatched in common events such as MessageSent which may need storage. Listeners may wish to automatically queue the handling of such events by implementing ShouldQueue. This currently results in a "serialization of 'closure' is not allowed" error, as the connection object passed in the event is not serializable.

A workaround is to manually create the queue job in the listener's handler, by first parsing the connection object. However this sometimes isn't ideal and adds complexity.

In the context of Reverb, I think it's particularly important the handling of events are easily queued to prevent blocking of the event loop.

@richt222 richt222 marked this pull request as draft October 26, 2024 09:39
@richt222 richt222 marked this pull request as ready for review October 26, 2024 11:07
@joedixon
Copy link
Collaborator

Thanks @richt222. Does this work with queued jobs immediately when adding this trait or is there still some work that needs to be done?

@richt222
Copy link
Author

Hey @joedixon, It works right away with no extras required. Tested with a DB queue. It was just the fact that the connection object could not be serialised directly in its current state. Adding the SerializesConnections trait solves that, as we're only serialising the bits we need. Similar to the SerializesChannels trait which the Channel already uses.

@@ -15,7 +15,6 @@ public function __serialize(): array
{
return [
'id' => $this->id(),
'identifier' => $this->identifier(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mark as ready for review when updated.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

identifier isn't a direct property of the Connection object being serialized, but was incorrectly being set as such when the object gets unserialized. This was causing PHPStan to fail static analysis.

The socket's raw identifier is resolved from the underlying WebSocketConnection which is passed in Connection's constructor. For this reason, it was removed from the Connection serialization, which currently only stores the "normalized" socket ID as one of its properties.

Maybe this PR needs more work to try and resurrect the entire connection when unserialized. Although that could be quite a rabbit hole.

@taylorotwell taylorotwell marked this pull request as draft October 29, 2024 14:37
@joedixon
Copy link
Collaborator

I dug into this some more and it's not actually possible to serialize the underlying connection, meaning you can't actually send any message to the connection once it's been unserialized. So, going to close this one since I don't think serializing it is providing much value.

@joedixon joedixon closed this Nov 27, 2024
@richt222
Copy link
Author

Thanks @joedixon. Yep, I agree. I also spent a good while trying to figure out if the underlying connection could be serialized and I think, although possible, it would be a big task and ultimately prone to failures.

The only slight frustration is that common events such as MessageSent can't be automatically queued as the event includes the connection. So listeners either require an extra step to create the queued job, minus the connection, or they get handled synchronously, which can obviously block the event loop.

@dpletiko
Copy link

dpletiko commented Nov 28, 2024

So, event though the SerializesConnections exist, it's not implemented on the Connection, which means that the listeners bound to Reverb events cannot be queued.

So, out of the box, there's no way to queue the listener for the MessageReceived event to parse/process the json payload and handle it however, without creating and manually dispatching a custom job from the "sync" listener.
Did I get this right?

Without diving too deep, is there a reason why the MessageReceived also has the Connection object passed along with stringified message?

Could we maybe have more events to handle just the message, or at least subscribe/unsubscribe events?

Thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants